package com.spdb.oa.type;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.spdb.oa.exception.OAException;

public class SubmitForm {

	public String processId;
	public String instanceId;
	public String distributionId;
	public String title;
	public Map<String, OpinionFormElement> opinionForm;
	public List<NextStep> nextSteps;
	@Override
	public String toString() {
		return "SubmitForm [processId=" + processId + ", instanceId=" + instanceId + ", distributionId="
				+ distributionId + ", title=" + title + ", opinionForm=" + opinionForm + ", nextSteps=" + nextSteps
				+ "]";
	}
	
	public static SubmitForm readFromJson(JsonParser parser) throws JsonParseException, IOException, OAException {
		SubmitForm sf = new SubmitForm();
		sf.opinionForm = new HashMap<String, OpinionFormElement>();
		sf.nextSteps = new ArrayList<NextStep>();
		
		if (parser.nextToken() != JsonToken.START_OBJECT) {
			throw new OAException("SubmitForm json data error: not start with object");
		}
		
		//skip the outer SubmitForm
		parser.nextToken();
		parser.nextToken();
		
		while (parser.nextToken() != JsonToken.END_OBJECT) {
			String fieldName = parser.getCurrentName();
			parser.nextToken();
			
			if (fieldName.equals("processId")) {
				sf.processId = parser.getValueAsString();
			} else if (fieldName.equals("instanceId")) {
				sf.instanceId = parser.getValueAsString();
			} else if (fieldName.equals("distributionId")) {
				sf.distributionId = parser.getValueAsString();
			} else if (fieldName.equals("title")) {
				sf.title = parser.getValueAsString();
			} else if (fieldName.equals("opinionForm")) {
				
				if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
					throw new OAException("SubmitForm json data error: not start with object [" + fieldName + "]");
				}
				//move to the opinionFormElement
				while (parser.nextToken() != JsonToken.END_OBJECT) {
					String opinionFormFieldName = parser.getCurrentName();
					parser.nextToken();
					if (opinionFormFieldName.equals("OpinionType") || opinionFormFieldName.equals("CommonOpinion")
							|| opinionFormFieldName.equals("SignOpinion") 
							|| opinionFormFieldName.equals("ReleaseType")
							|| opinionFormFieldName.equals("LDSQ")) {
						if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
							throw new OAException(
									"SubmitForm json data error: not start with object [" + opinionFormFieldName + "]");
						}
						ChoiceOpinionFormElement ofe = new ChoiceOpinionFormElement();
						ofe.chioces = new ArrayList<ChoiceOpinionFormElement.Chioce>();
						while (parser.nextToken() != JsonToken.END_OBJECT) {
							String choiceDataTypeFieldName = parser.getCurrentName();
							parser.nextToken();
							if (choiceDataTypeFieldName.equals("id")) {
								ofe.id = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("name")) {
								ofe.name = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("displayName")) {
								ofe.displayName = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("controlType")) {
								ofe.controlType = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("required")) {
								ofe.required = parser.getValueAsBoolean();
							} else if (choiceDataTypeFieldName.equals("visible")) {
								ofe.visible = parser.getValueAsBoolean();
							} else if (choiceDataTypeFieldName.equals("enabled")) {
								ofe.enabled = parser.getValueAsBoolean();
							} else if (choiceDataTypeFieldName.equals("dataType")) {
								ofe.dataType = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("defaultChoice")) {
								ofe.defaultChoice = parser.getValueAsString();
							} else if (choiceDataTypeFieldName.equals("chioces")) {
								if (parser.getCurrentToken() != JsonToken.START_ARRAY) {
									throw new OAException("SubmitForm json data error: not start with array ["
											+ choiceDataTypeFieldName + "]");
								}
								while (parser.nextToken() != JsonToken.END_ARRAY) {
									if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
										throw new OAException("SubmitForm json data error: not start with object ["
												+ choiceDataTypeFieldName + "]");
									}
									ChoiceOpinionFormElement.Chioce choice = new ChoiceOpinionFormElement.Chioce();
									//for every choice in choices list
									while (parser.nextToken() != JsonToken.END_OBJECT) {
										String choiceFieldName = parser.getCurrentName();
	
										parser.nextToken();
										if (choiceFieldName.equals("value")) {
											choice.value = parser.getValueAsString();
										} else if (choiceFieldName.equals("content")) {
											choice.content = parser.getValueAsString();
										} else if (choiceFieldName.equals("description")) {
											choice.description = parser.getValueAsString();
										} else if (choiceFieldName.equals("selected")) {
											choice.selected = parser.getValueAsBoolean();
										} else {
										
											throw new OAException("SubmitForm json data error: not start with object ["
													+ choiceFieldName + "]");

										}
										
									}
									ofe.chioces.add(choice);
								}

								}

							}
						sf.opinionForm.put(opinionFormFieldName, ofe);
					} else if (opinionFormFieldName.equals("Limited")) {
						if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
							throw new OAException("SubmitForm json data error: not start with object [" + opinionFormFieldName + "]");
						}
						LimitedOpinionFormElement ofe = new LimitedOpinionFormElement();

						while (parser.nextToken() != JsonToken.END_OBJECT) {
							String limitedFiledName = parser.getCurrentName();
							parser.nextToken();

							if (limitedFiledName.equals("id")) {
								ofe.id = parser.getValueAsString();
							} else if (limitedFiledName.equals("name")) {
								ofe.name = parser.getValueAsString();
							} else if (limitedFiledName.equals("displayName")) {
								ofe.displayName = parser.getValueAsString();
							} else if (limitedFiledName.equals("controlType")) {
								ofe.controlType = parser.getValueAsString();
							} else if (limitedFiledName.equals("required")) {
								ofe.required = parser.getValueAsBoolean();
							} else if (limitedFiledName.equals("visible")) {
								ofe.visible = parser.getValueAsBoolean();
							} else if (limitedFiledName.equals("enabled")) {
								ofe.enabled = parser.getValueAsBoolean();
							} else if (limitedFiledName.equals("dataType")) {
								ofe.dataType = parser.getValueAsString();
							} else if (limitedFiledName.equals("min")) {
								ofe.min = parser.getValueAsString();
							} else if (limitedFiledName.equals("max")) {
								ofe.max = parser.getValueAsString();
							} else if (limitedFiledName.equals("defaultValue")) {
								ofe.defaultValue = parser.getValueAsString();
							} else if (limitedFiledName.equals("content")) {
								ofe.content = parser.getValueAsString();
							}
							else {
								throw new OAException("Unknown field name: " + limitedFiledName);
							}
						}
						
						sf.opinionForm.put("Limited", ofe);
					} else if (opinionFormFieldName.equals("Opinion")) {
						if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
							throw new OAException("SubmitForm json data error: not start with object [" + opinionFormFieldName + "]");
						}
						OpinionFormElement ofe = new OpinionFormElement();

						while (parser.nextToken() != JsonToken.END_OBJECT) {
							String opinionFiledName = parser.getCurrentName();
							parser.nextToken();

							if (opinionFiledName.equals("id")) {
								ofe.id = parser.getValueAsString();
							} else if (opinionFiledName.equals("name")) {
								ofe.name = parser.getValueAsString();
							} else if (opinionFiledName.equals("displayName")) {
								ofe.displayName = parser.getValueAsString();
							} else if (opinionFiledName.equals("controlType")) {
								ofe.controlType = parser.getValueAsString();
							} else if (opinionFiledName.equals("required")) {
								ofe.required = parser.getValueAsBoolean();
							} else if (opinionFiledName.equals("visible")) {
								ofe.visible = parser.getValueAsBoolean();
							} else if (opinionFiledName.equals("enabled")) {
								ofe.enabled = parser.getValueAsBoolean();
							} else if (opinionFiledName.equals("dataType")) {
								ofe.dataType = parser.getValueAsString();
							} else if (opinionFiledName.equals("content")) {
								ofe.content = parser.getValueAsString();
							} else {
							
								throw new OAException("Unknown field name: " + opinionFiledName);	
							}
						}
						
						sf.opinionForm.put("Opinion", ofe);

					} else {
						throw new OAException("Unknown field name: " + opinionFormFieldName);
					}
				}
				
				
			} else if (fieldName.equals("nextSteps")) {
				if (parser.getCurrentToken() != JsonToken.START_ARRAY) {
					throw new OAException("SubmitForm json data error: not start with array [" + fieldName + "]");
				}
				while (parser.nextToken() != JsonToken.END_ARRAY) {
					NextStep ns = new NextStep();
					if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
						throw new OAException("SubmitForm json data error: not start with object [" + fieldName + "]");
					}
					while (parser.nextToken() != JsonToken.END_OBJECT) {
						String nextStepFieldName = parser.getCurrentName();
						parser.nextToken();
						if (nextStepFieldName.equals("id")) {
							ns.id = parser.getValueAsString();
						} else if (nextStepFieldName.equals("activityId")) {
							ns.activityId = parser.getValueAsString();
						} else if (nextStepFieldName.equals("name")) {
							ns.name = parser.getValueAsString();
						} else if (nextStepFieldName.equals("displayName")) {
							ns.displayName = parser.getValueAsString(); 
						} else if (nextStepFieldName.equals("displayType")) {
							ns.displayType = parser.getValueAsString();
						} else if (nextStepFieldName.equals("single")) {
							ns.single = parser.getValueAsString();
						} else if (nextStepFieldName.equals("feedbackFunctionName")) {
							ns.feedbackFunctionName = parser.getValueAsString();
						} else if (nextStepFieldName.equals("feedbackParameter")) {
							ns.feedbackParameter = parser.getValueAsString();
						} else if (nextStepFieldName.equals("users")) {
							ns.users = new ArrayList<NextStep.User>();
							
							if (parser.getCurrentToken() != JsonToken.START_ARRAY) {
								throw new OAException("SubmitForm json data error: not start with array [" + nextStepFieldName + "]");
							}
							while (parser.nextToken() != JsonToken.END_ARRAY) {
								NextStep.User user = new NextStep.User();
								if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
									throw new OAException("SubmitForm json data error: not start with object [" + nextStepFieldName + "]");
								}
								while (parser.nextToken() != JsonToken.END_OBJECT) {
									String userFieldName = parser.getCurrentName();
									parser.nextToken();
									if (userFieldName.equals("id")) {
										user.id = parser.getValueAsString();
									} else if (userFieldName.equals("userName")) {
										user.userName = parser.getValueAsString();
									} else if (userFieldName.equals("displayName")) { 
										user.displayName = parser.getValueAsString();
									} else if (userFieldName.equals("userAccount")) {
										user.userAccount = parser.getValueAsString();
									} else if (userFieldName.equals("deptId")) {
										user.deptId = parser.getValueAsString();
									} else if (userFieldName.equals("deptName")) {
										user.deptName = parser.getValueAsString();
									} else if (userFieldName.equals("companyId")) {
										user.companyId = parser.getValueAsString();
									} else if (userFieldName.equals("companyName")) {
										user.companyName = parser.getValueAsString();
									} else if (userFieldName.equals("content")) {
										user.content = parser.getValueAsString();
									} else if (userFieldName.equals("feedbackParameter")) {
										user.feedbackParameter = parser.getValueAsString();
									} else {
										throw new OAException("Unknown field name: " + userFieldName);
									}
									
										
								}
								
								ns.users.add(user);
							}
						}
						
					}
					sf.nextSteps.add(ns);
				}
			} else {
				throw new OAException("Unknown field: " + fieldName);
			}
			
		}
		
		parser.close();
		
		return sf;
		
	}
}
